package paim.wingchun.app;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;

import org.hsqldb.Server;
import org.hsqldb.ServerConstants;
import org.hsqldb.persist.HsqlDatabaseProperties;




public class HyperSQLs {

    private static Server servidor;

    static final String ipPadrao = "localhost";

    static final String DRIVER = "org.hsqldb.jdbcDriver";


    /** Informa o tipo de formato utilizado pelo script do banco (0 : texto , 1 : binario, 3 : binario comprimido)) */
    public static final byte FORMATO_SCRIPT_BD = (Constantes.ESTAGIO == Estagio.ALPHA ? (byte) 0 : (byte) 3);

    public static Server getServidor() {
        return servidor;
    }

    public static boolean isOnline() {
        if ( servidor != null )
            return ServerConstants.SERVER_STATE_ONLINE == servidor.getState();

        return false;
    }

    public static void start() throws Throwable {
        start(true, Constantes.App$banco, Constantes.App$usuario, Constantes.App$senha);
    }

    public static void start(boolean modoServidor, String nomeBanco, String user, String senha) throws Throwable {
        start(true, nomeBanco, ipPadrao, ServerConstants.SC_DEFAULT_HSQL_SERVER_PORT, user, senha);
    }

    public static void start(boolean modoServidor, String nomeBanco, String ip, int portaTCP, String user, String senha)
                    throws Throwable {
        if ( isOnline() )
            return;

        if ( modoServidor ) {
            servidor = new Server();
            /* Desabilita o log do hsqldb */
            // servidor.setLogWriter(null);
            // servidor.setErrWriter(null);
            // servidor.setTrace(false);
            servidor.setSilent(true);
            servidor.setAddress(ip);
            servidor.setPort(portaTCP);
            servidor.setDatabaseName(0, nomeBanco);
            /* Seta o caminho do banco informando o formato do script DDL utilizado */
            servidor.setDatabasePath(0, WC_File.getAppHomePath() + nomeBanco + ";"
                            + HsqlDatabaseProperties.hsqldb_script_format + "=" + FORMATO_SCRIPT_BD);
            servidor.start();
        }
        else {
            Class.forName(DRIVER).newInstance();
            DriverManager.getConnection(url_file() + nomeBanco, user, senha);
        }
    }

    public static void shutdown() throws SQLException, InterruptedException {
        /* http://melloware.com/products/jukes/xref/com/melloware/jukes/db/Database.html */
        if ( servidor != null ) {
            Hibernates.shutdown();

            // FIXME o finalizar
            // connection.close();
            // st.close();
            // connection.commit();
            // session.close();
            // session.disconnect();
            // servidor.shutdown();
            servidor.stop();

            while ( servidor.getState() != ServerConstants.SERVER_STATE_SHUTDOWN ) {
                WC_Log.getInstancia().getlogger().log(Level.INFO, "Sleeping waiting for server to stop");
                Thread.sleep(100);
            }

        }
        servidor = null;
    }

    static String url() {
        return "jdbc:hsqldb:hsql://" + servidor.getAddress() + ":" + servidor.getPort() + "/"
                        + servidor.getDatabaseName(0, true);
    }

    static String url_file() {
        return "jdbc:hsqldb:file:" + WC_File.getAppHomePath();
    }

    public static Connection getConnection(String nomeBanco, String portaTCP, String user, String senha)
                    throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
        String url;
        if ( isOnline() )
            url = url();
        else
            url = url_file() + nomeBanco;

        Class.forName(DRIVER).newInstance();
        return DriverManager.getConnection(url, user, senha);
    }

}
